package com.md.config.bean;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.md.config.client.ClientConfiguration;
import com.md.config.demo.DemoClient;
import com.md.config.demo.DemoInterface;
import com.md.util.system.Snowflake;
import org.apache.http.config.SocketConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Optional;

/**
 * @author 刘骄阳
 * 2022-03-14 15:04
 */
@Configuration
public class MyBean {
  /**
   * 序列化
   */
  @Bean
  public ObjectMapper serializingObjectMapper() {
    JavaTimeModule module = new JavaTimeModule();
    LocalDateTimeDeserializer dateTimeDeserializer =
      new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    LocalDateTimeSerializer dateTimeSerializer =
      new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    module.addDeserializer(LocalDateTime.class, dateTimeDeserializer);
    module.addSerializer(LocalDateTime.class, dateTimeSerializer);
    return Jackson2ObjectMapperBuilder.json().modules(module)
      .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS).build();
  }

  /**
   * 雪花算法
   */
  @Bean
  public Snowflake snowflake(final SnowflakeConfig snowflakeConfig) {
    SnowflakeConfig localSnowFlake = Optional.ofNullable(snowflakeConfig).orElse(new SnowflakeConfig());
    return new Snowflake(localSnowFlake.getWorkerId(), localSnowFlake.getDatacenterId(),
      0L, localSnowFlake.getStartTime());
  }

  /**
   * restTemplate
   */
  @Bean
  public RestTemplate restTemplate(final ClientConfiguration clientConfiguration) {
    RestTemplate restTemplate = new RestTemplate();
    // 创建连接池管理器
    PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
    poolingConnManager.setMaxTotal(100); // 设置最大连接数
    poolingConnManager.setDefaultMaxPerRoute(10); // 每个路由的最大连接数

    // 设置连接池中的连接保持时间
    poolingConnManager.setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(30 * 1000).build());

    // 创建 HttpClient 并设置连接池
    CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(poolingConnManager).build();

    // 创建 RestTemplate 并设置请求工厂
    HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);

    // 连接超时时间
    requestFactory.setConnectTimeout(clientConfiguration.getConnectTimeout());
    // 请求超时时间
    requestFactory.setReadTimeout(clientConfiguration.getReadTimeout());
    // 配置拦截器
    restTemplate.setInterceptors(clientConfiguration.getInterceptors());
    return restTemplate;
  }

  @Bean
  @ConditionalOnBean(DemoInterface.class)
  public DemoClient demoClient(final DemoInterface demoInterface,
                               final NacosDiscoveryProperties nacosDiscoveryProperties,
                               final InetUtils inetUtils) {
    return new DemoClient(nacosDiscoveryProperties, demoInterface, inetUtils);
  }
}
